//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

use crate::notice_decode::new_wrong_session_notice;
use proto_gen_rust::roadmap_user_api::roadmap_user_api_client::RoadmapUserApiClient;
use proto_gen_rust::roadmap_user_api::*;
use tauri::{
    plugin::{Plugin, Result as PluginResult},
    AppHandle, Invoke, PageLoadPayload, Runtime, Window,
};

#[tauri::command]
async fn set_access<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: SetAccessRequest,
) -> Result<SetAccessResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = RoadmapUserApiClient::new(chan.unwrap());
    match client.set_access(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == set_access_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("set_access".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn list_access<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: ListAccessRequest,
) -> Result<ListAccessResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = RoadmapUserApiClient::new(chan.unwrap());
    match client.list_access(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_access_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("list_access".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn remove_access<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: RemoveAccessRequest,
) -> Result<RemoveAccessResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = RoadmapUserApiClient::new(chan.unwrap());
    match client.remove_access(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == remove_access_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("remove_access".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn get_learn_state<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: GetLearnStateRequest,
) -> Result<GetLearnStateResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = RoadmapUserApiClient::new(chan.unwrap());
    match client.get_learn_state(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == get_learn_state_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("get_learn_state".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn set_note<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: SetNoteRequest,
) -> Result<SetNoteResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = RoadmapUserApiClient::new(chan.unwrap());
    match client.set_note(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == set_note_response::Code::WrongSession as i32 {
                if let Err(err) = window.emit("notice", new_wrong_session_notice("set_note".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn list_note<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: ListNoteRequest,
) -> Result<ListNoteResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = RoadmapUserApiClient::new(chan.unwrap());
    match client.list_note(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_note_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("list_note".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn list_my_note<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: ListMyNoteRequest,
) -> Result<ListMyNoteResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = RoadmapUserApiClient::new(chan.unwrap());
    match client.list_my_note(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_my_note_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("list_my_note".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn remove_note<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: RemoveNoteRequest,
) -> Result<RemoveNoteResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = RoadmapUserApiClient::new(chan.unwrap());
    match client.remove_note(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == remove_note_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("remove_note".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}


#[tauri::command]
async fn list_note_roadmap<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: ListNoteRoadmapRequest,
) -> Result<ListNoteRoadmapResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = RoadmapUserApiClient::new(chan.unwrap());
    match client.list_note_roadmap(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_note_roadmap_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("list_note_roadmap".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

pub struct RoadmapUserApiPlugin<R: Runtime> {
    invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync + 'static>,
}

impl<R: Runtime> RoadmapUserApiPlugin<R> {
    pub fn new() -> Self {
        Self {
            invoke_handler: Box::new(tauri::generate_handler![
                set_access,
                list_access,
                remove_access,
                get_learn_state,
                set_note,
                list_note,
                list_my_note,
                remove_note,
                list_note_roadmap,
            ]),
        }
    }
}

impl<R: Runtime> Plugin<R> for RoadmapUserApiPlugin<R> {
    fn name(&self) -> &'static str {
        "roadmap_user_api"
    }
    fn initialization_script(&self) -> Option<String> {
        None
    }

    fn initialize(&mut self, _app: &AppHandle<R>, _config: serde_json::Value) -> PluginResult<()> {
        Ok(())
    }

    fn created(&mut self, _window: Window<R>) {}

    fn on_page_load(&mut self, _window: Window<R>, _payload: PageLoadPayload) {}

    fn extend_api(&mut self, message: Invoke<R>) {
        (self.invoke_handler)(message)
    }
}
